package com.linshidream.intrachat.simplenio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;

/**
 * Created on 2025/7/24 18:25
 *
 * @author linshidream
 * @version 1.0.0
 * @description
 */

public class NioSimpleClient {

    public static void main(String[] args) throws IOException {

        // 1、客户端开启连接
        SocketChannel client = SocketChannel.open();
        client.configureBlocking(false);
        client.connect(new InetSocketAddress("localhost", 10000));

        // 2、打开一个监听器 并订阅连接事件
        Selector selector = Selector.open();
        client.register(selector, SelectionKey.OP_CONNECT);

        System.out.println("NIO 单线程客户端启动完成...");

        // 3、主循环监听事件开始轮询
        while (true) {
            // 阻塞直到有事件
            selector.select();

            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            while (iterator.hasNext()) {
                SelectionKey key = iterator.next();
                // 用完记得删除事件
                iterator.remove();

                if (key.isConnectable()) {
                    SocketChannel channel = (SocketChannel) key.channel();
                    System.out.println("客户端已连接到服务端：" + channel.getRemoteAddress());

                    // 建立连接后，再订阅写事件
                    if (channel.finishConnect()) {
                        channel.register(selector, SelectionKey.OP_WRITE);
                    }
                }

                if (key.isWritable()) {
                    SocketChannel channel = (SocketChannel) key.channel();
                    String msg = "Hello Server\n";
                    ByteBuffer buffer = ByteBuffer.wrap(msg.getBytes(StandardCharsets.UTF_8));
                    channel.write(buffer);
                    System.out.println("客户端发送消息：" + msg);

                    // 写完数据，需要订阅读事件（读服务端响应数据）
                    channel.register(selector, SelectionKey.OP_READ);
                }

                if (key.isReadable()) {
                    SocketChannel channel = (SocketChannel) key.channel();
                    ByteBuffer buffer = ByteBuffer.allocate(1024);
                    int len = channel.read(buffer);
                    if (len > 0) {
                        buffer.flip();
                        String resp = new String(buffer.array(), 0, len, StandardCharsets.UTF_8).trim();
                        System.out.println("客户端收到服务端响应：" + resp);

                        // 发一次就关闭
                        channel.close();
                        return;
                    }
                }
            }
        }
    }
}
